// axios config
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'
import Nprogress from 'nprogress'
import { AxiosCanceler } from './helper/axiosCancel'
import { store } from '@/redux'
import { message } from 'antd'
import { setToken, setUserInfo } from '@/redux/modules/global/action'
import { checkStatus } from './helper/checkStatus'

const axiosCanceler = new AxiosCanceler()

const config = {
  baseURL: import.meta.env.VITE_API_URL,
  timeout: 15000, // 请求超时时间15s
  headers: {
    'Content-Type': 'application/json;charset=UTF-8'
  },
  withCredentials: true, // 跨域时允许携带凭证
}

class RequestHttp {
    service: AxiosInstance;
    public constructor(config: AxiosRequestConfig) {
      this.service = axios.create(config)
      this.service.interceptors.request.use(
        (config) => {
            Nprogress.start();
            // 将当前请求添加到pending中
            axiosCanceler.addPending(config)
            const token = store.getState().user.token
            if (token) {
              config.headers!.Authorization = token
            }
          return config
        },
        (error) => {
          return Promise.reject(error)
        }
      )
      this.service.interceptors.response.use(
        (response: AxiosResponse) => {
          const { data, config} = response
          Nprogress.done()
        //   移除当前请求
          axiosCanceler.removePending(config)
          if (data.code && data.code !== 200) {
            message.error(data.msg)
            return Promise.reject(data)
          }
          return data
        },
        (error) => {
            Nprogress.done()
          const { response } = error
          if (response) {
            // 请求已发出，但是不在2xx的范围
            //登录失效处理
            if (response.status === 401) {
                store.dispatch(setToken(''))
                store.dispatch(setUserInfo({}))
                message.error('登录失效，请重新登录')
                window.location.href = '/login'
                return Promise.reject(error)
            }
            // 请求超时
            if (error.message.includes('timeout')) {
                message.error('请求超时')
                return Promise.reject(error)
            }
            if (response) {
                checkStatus(response.status)
            }
            return Promise.reject(error)
          } else {
            // 处理断网的情况
            // eg:请求超时或断网时，更新state的network状态
            // network状态在app.vue中控制着一个全局的断网提示组件的显示隐藏
        }
      }
      )
  }
}

export default new RequestHttp(config)